
#include "Particle.h"
#include <cstdlib>
#include "..\\..\\SGD Wrappers\SGD_GraphicsManager.h"
#include "..\\Game Objects\Camera.h"
#include "..\\Definitions.h"

#define FRICTION 0.2f

Particle::Particle()
{
}


Particle::~Particle()
{
}

// Accessors
float Particle::GetLifeEnd()
{
	return fLifeEnd;
}

float Particle::GetLife()
{
	return fLife;
}

float Particle::GetRotation()
{
	return fRotation;
}

float Particle::GetColorA()
{
	return fColorA;
}

float Particle::GetColorR()
{
	return fColorR;
}

float Particle::GetColorG()
{
	return fColorG;
}

float Particle::GetColorB()
{
	return fColorB;
}

float Particle::GetColorChangeA()
{
	return fColorChangeA;
}

float Particle::GetColorChangeR()
{
	return fColorChangeR;
}

float Particle::GetColorChangeG()
{
	return fColorChangeG;
}

float Particle::GetColorChangeB()
{
	return fColorChangeB;
}

float Particle::GetScale()
{
	return fScale;
}

float Particle::GetScaleChange()
{
	return fScaleChange;
}

float Particle::GetSpeed()
{
	return fSpeed;
}

float Particle::GetSpeedChange()
{
	return fSpeedChange;
}

SGD::Vector Particle::GetAcceleration()
{
	return acceleration;
}

SGD::Vector Particle::GetVelocity()
{
	return velocity;
}

SGD::Point Particle::GetPosition()
{
	return position;
}

// Mutators
void Particle::SetLifeEnd(float life)
{
	fLifeEnd = life;
}

void Particle::SetLife(float life)
{
	fLife = life;
}

void Particle::SetRotation(float rotation)
{
	fRotation = rotation;
}

void Particle::SetColorA(float color)
{
	fColorA = color;
}

void Particle::SetColorR(float color)
{
	fColorR = color;
}

void Particle::SetColorG(float color)
{
	fColorG = color;
}

void Particle::SetColorB(float color)
{
	fColorB = color;
}

void Particle::SetColorChangeA(float color)
{
	fColorChangeA = color;
}

void Particle::SetColorChangeR(float color)
{
	fColorChangeR = color;
}

void Particle::SetColorChangeG(float color)
{
	fColorChangeG = color;
}

void Particle::SetColorChangeB(float color)
{
	fColorChangeB = color;
}

void Particle::SetScale(float scale)
{
	fScale = scale;
}

void Particle::SetScaleChange(float scale)
{
	fScaleChange = scale;
}

void Particle::SetSpeed(float speed)
{
	fSpeed = speed;
}

void Particle::SetSpeedChange(float speed)
{
	fSpeedChange = speed;
}

void Particle::SetAcceleration(SGD::Vector v)
{
	acceleration = v;
}

void Particle::SetVelocity(SGD::Vector v)
{
	velocity = v;
}

void Particle::SetPosition(SGD::Point p)
{
	position = p;
}

void Particle::Reset(Flyweight f)
{
	switch (f.GetEmitterType())
	{
	case 1: // Line
	{
		int spawn = rand() % f.GetEmitterWidth() + 1;
		spawn -= f.GetEmitterWidth() >> 1;
		SGD::Vector pos = { (float)spawn, 0.0f };
		float angle = f.GetStartVelocity().ComputeAngle(SGD::Vector(0, -1));
		pos.Rotate(angle);
		SetPosition(SGD::Point(f.GetPosition().x + pos.x, f.GetPosition().y + pos.y));
		break;
	}
	case 2: // Circle
	{
		int spawn = rand() % f.GetEmitterWidth() + 1;
		int rot = rand() % 360;
		SGD::Vector pos = { (float)spawn, 0.0f };
		pos.Rotate((float)rot);
		SetPosition(SGD::Point(f.GetPosition().x + pos.x, f.GetPosition().y + pos.y));
		break;
	}
	case 3: // Rectangle
	{
		int spawnX = rand() % f.GetEmitterWidth() + 1;
		spawnX -= f.GetEmitterWidth() >> 1;
		int spawnY = rand() % f.GetEmitterHeight() + 1;
		spawnY -= f.GetEmitterHeight() >> 1;
		SetPosition(SGD::Point(f.GetPosition().x + (float)spawnX, f.GetPosition().y + (float)spawnY));
		break;
	}
	case 0: // Point
	default:
	{
		SetPosition(f.GetPosition());
	}
	}
	
	// Set Life End
	int min = (int)(f.GetMinLife() * 100);
	int max = (int)((f.GetMinLife() + f.GetMaxLife() * 100));
	SetLifeEnd((float)(((rand() % max) + min) / 100));

	// Set Particle Speed
	SetSpeed(f.GetStartSpeed());
	SetSpeedChange((f.GetEndSpeed() - f.GetStartSpeed()) / GetLifeEnd());

	// Set Particle Color
	SetColorA(f.GetStartColorA());
	SetColorR(f.GetStartColorR());
	SetColorG(f.GetStartColorG());
	SetColorB(f.GetStartColorB());

	SetColorChangeA((f.GetEndColorA() - f.GetStartColorA()) / GetLifeEnd());
	SetColorChangeR((f.GetEndColorR() - f.GetStartColorR()) / GetLifeEnd());
	SetColorChangeG((f.GetEndColorG() - f.GetStartColorG()) / GetLifeEnd());
	SetColorChangeB((f.GetEndColorB() - f.GetStartColorB()) / GetLifeEnd());

	// Set Life
	SetLife(0.0f);

	// Set Rotation
	SetRotation(0.0f);
	
	// Set Scale
	SetScale(f.GetStartScale());
	SetScaleChange((f.GetEndScale() - f.GetStartScale()) / GetLifeEnd());

	int iRange = rand() % f.GetEmitterRange();
	iRange -= f.GetEmitterRange() >> 1;
	float range = ((float)iRange * SGD::PI) / 180.0f;

	// Set Acceleration
	SGD::Vector acc = { 0, -1.0f * GetSpeedChange() };
	if (f.GetAngle() != 0)
		acc.Rotate(f.GetAngle());
	acc.Rotate(range);
	SetAcceleration(acc);

	// Set Velocity
	SGD::Vector vel = { 0, -1.0f * GetSpeed() };
	if (f.GetAngle() != 0)
		vel.Rotate(f.GetAngle());
	vel.Rotate(range);
	SetVelocity(vel);
}

bool Particle::Update(Flyweight f, float dt)
{
	SetLife(GetLife() + dt);
	if (GetLife() > GetLifeEnd())
	{
		return false;
	}
	else
	{
		// Update Color
		SetColorA(GetColorA() + (GetColorChangeA() * dt));
		SetColorR(GetColorR() + (GetColorChangeR() * dt));
		SetColorG(GetColorG() + (GetColorChangeG() * dt));
		SetColorB(GetColorB() + (GetColorChangeB() * dt));

		// Update Scale, Speed, and Rotation
		SetScale(GetScale() + (GetScaleChange() * dt));
		SetSpeed(GetSpeed() + (GetSpeedChange() * dt));
		SetRotation(GetRotation() + (f.GetRotationRate() * dt));

		// Update Acceleration
		//SGD::Vector acc = SGD::Vector(0, -1 * GetSpeedChange());
		//acc.Rotate(GetAcceleration().ComputeAngle(SGD::Vector(0, -1)));
		//SetAcceleration(acc);

		// Apply Gravity?
		if (f.GetGravity())
		{
			SGD::Vector Fnet = GetAcceleration() * f.GetWeight();
			Fnet += SGD::Vector(0.0f, 9.82f);
			SetAcceleration(Fnet / f.GetWeight());
		}

		// Update Velocity
		SetVelocity(GetVelocity() + (GetAcceleration() * dt));

		// Update Position
		SetPosition(GetPosition() + (GetVelocity() * dt));
	}
	return true;
}

void Particle::Render(Flyweight f)
{
	SGD::Point offset = GetPosition();
	offset.x -= CAMERA->GetPosition().x;
	offset.y -= CAMERA->GetPosition().y;
	SGD::GraphicsManager::GetInstance()->DrawTextureSection(f.GetImage(), offset, f.GetDrawRect(), GetRotation(), f.GetCenterPoint(), SGD::Color((unsigned char)(GetColorA() * 255), (unsigned char)(GetColorR() * 255), (unsigned char)(GetColorG() * 255), (unsigned char)(GetColorB() * 255)), SGD::Size(GetScale(), GetScale()));
}